home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 41.zip / BS1 part 41 / Lattice C v5.02 d4.adf / examples / speechtoy.c < prev   
C/C++ Source or Header  |  1988-11-07  |  48KB  |  1,380 lines

  1. /* This program was written to show the use of gadgets in a
  2.  * window. Thus one menu, one auto requester, but lots of
  3.  * gadget types.
  4.  * For the sake of example, two mutual exclude gadgets
  5.  * (female/male) are shown that perform a function that might
  6.  * be better implemented as a toggle image, in a manner similar
  7.  * to that shown in the inflection Mode gadget.
  8.  * Again for the sake of example, the proportional gadgets
  9.  * are generated dynamicly (that is, copied from a template and
  10.  * filled in), whereas most gadgets are declared staticly in
  11.  * the struct declaration, which saves the initialization code
  12.  * space.
  13.  * Lastly, for the sake of example, this program is extremely
  14.  * verbose in the way of comments. Hope you don't mind.
  15.  */
  16. /* Written by David M Lucas. */
  17. /* If you find somthing you don't like, fix it! Have fun! */
  18. /* Thanks Amiga. */
  19.  
  20. #include "exec/types.h"
  21. #include "exec/exec.h"
  22. #include "intuition/intuition.h"
  23. #include "intuition/intuitionbase.h"
  24. #include "graphics/regions.h"
  25. #include "graphics/copper.h"
  26. #include "graphics/gels.h"
  27. #include "graphics/gfxbase.h"
  28. #include "devices/keymap.h"
  29. #include "hardware/blit.h"
  30. #include "devices/narrator.h"
  31. #include "libraries/translator.h"
  32.  
  33. /* #define DEBUG */
  34.  
  35. /* Revision number is used on calls to OpenLibrary
  36.  * to let the system know what revision level the
  37.  * program was written for. Usually refers to the
  38.  * ROM release number or the release number of a
  39.  * disk based library.
  40.  */
  41. #define REVISION 1
  42.  
  43. #define CONTWINDW 321 /* Overall Control Window Width/Height */
  44. #define CONTWINDH 123
  45. #define FACEWINDW 32  /* Overall Face Window Width / Height */
  46. #define FACEWINDH 44  /* this includes borders, incedently */
  47.  
  48. /* Pen numbers to draw gadget borders/images/text with */
  49. #define REDP   3        /* color in register 3 once was red */
  50. #define BLKP   2        /* color in register 2 was black */
  51. #define WHTP   1        /* color in register 1 was white */
  52. #define BLUP   0        /* color in register 0 was blue */
  53. /* the length of the English and phonetic buffers */
  54. #define ESTRINGSIZE 512
  55. #define PSTRINGSIZE 768 /* phonemes are longer than english */
  56.  
  57. #define NUMPROPS 4      /* number of proportional gadgets */
  58.  
  59. /* Ranges of proportional data */
  60. #define RNGFREQ  (MAXFREQ  - MINFREQ)  +1
  61. #define RNGRATE  (MAXRATE  - MINRATE)  +1
  62. #define RNGPITCH (MAXPITCH - MINPITCH) +1
  63. #define RNGVOL   (MAXVOL   - MINVOL)   +1
  64.  
  65. struct TextAttr TestFont = /* Needed for opening screen */
  66.    {
  67.    (STRPTR)"topaz.font",
  68.    TOPAZ_EIGHTY, 0, 0
  69.    };
  70.  
  71. /* Which audio channels to use */
  72. BYTE audio_chan[] = {3, 5, 10, 12};
  73. /* Pointer to translator library vectors */
  74. struct Library *TranslatorBase = 0;
  75. struct MsgPort talk_port; /* Message port for the say's I/O  */
  76. struct MsgPort read_port; /* Message port for the say's I/O  */
  77. struct mouth_rb mouth_io;  /* IO Request block, mouth flavor */
  78. /* IO Request block, narrator flavor */
  79. struct narrator_rb voice_io;
  80. /* indicative of the Open return */
  81. UBYTE NarratorOpenError = 0;
  82. /* indicative of a Translations success */
  83. UBYTE TranslatorError = 0;
  84. USHORT i;
  85.  
  86. /* These are used to draw the eyes and mouth size relative */
  87. USHORT MouthWMult;
  88. USHORT EyesLeft;
  89. USHORT MouthHMult;
  90. USHORT EyesTop;
  91. USHORT EyesBottom;
  92. USHORT YMouthCenter;  /* Pixels from top edge */
  93. USHORT XMouthCenter;  /* Pixels from left edge */
  94. USHORT yaw;
  95. USHORT LipWidth, LipHeight;
  96.  
  97. /* String Gadgets *********************************************
  98.  * First the string gadgets.
  99.  * 1) because the Phonetic string is refreshed programaticly
  100.  * (that is, deleted and added again) quite often, and doing
  101.  * this requires the use of RefreshGadgets(), and this causes
  102.  * gadgets that are closer to the beginning of the list than
  103.  * the gadget given to RefreshGadgets() to flicker.
  104.  * 2) because they don't flicker when OTHER gadgets
  105.  * (ie female/male, coming up) are deleted and added.
  106.  */
  107. /* These'll be used to put a nice double line border around
  108.  * each of the two string gadgets.
  109.  */
  110. /* y,x pairs drawn as a connected line. Be sure to have an even
  111.  * number of arguments (ie complete pairs).
  112.  */
  113.  
  114. USHORT StrVectors[] = {
  115.    0, 0,   297, 0,   297, 14,   0, 14,
  116.    0, 1,   296, 1,   296, 13,   1, 13,
  117.    1, 1
  118. };
  119. struct Border StrBorder = {
  120.    -4, -3,           /* initial offsets, gadget relative */
  121.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  122.    9,                /* number of vectors */
  123.    StrVectors,     /* pointer to the actual array of vectors */
  124.    NULL       /* no next Border, can point to another border */
  125. };
  126.  
  127. /* The same undo buffer is used for both string gadgets,
  128.  * this is sized to largest so that largest fits.
  129.  */
  130. UBYTE UndoBuffer[PSTRINGSIZE];
  131.  
  132. /* English String Gadget is where the user types in English */
  133. /* default text */
  134. UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
  135. struct StringInfo EnglInfo = {
  136.    EnglBuffer,    /* pointer to I/O buffer */
  137.    UndoBuffer,    /* pointer to undo buffer */
  138.    0,             /* buffer position */
  139.    ESTRINGSIZE,   /* max number of chars, including NULL */
  140.    0, 0,          /* first char in display, undo positions */
  141.    24,          /* number of chars (currently) in the buffer */
  142.    0, 0, 0,    /* position variables calculated by Intuition */
  143.    NULL,          /* no pointer to RastPort */
  144.    0,             /* not a LongInt string gadget */
  145.    NULL           /* no pointer to alternate keymap */
  146. };
  147. struct IntuiText EnglText = {
  148.    WHTP, BLUP,    /* FrontPen, BackPen */
  149.    JAM1,          /* DrawMode */
  150.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  151.    &TestFont,     /* pointer to TextFont */
  152.    "English:",    /* pointer to Text */
  153.    NULL           /* no pointer to NextText */
  154. };
  155. struct Gadget EnglStrGadget = {
  156.    NULL,             /* pointer to Next Gadget */
  157.    11, 63, 290, 10,  /* (Left Top Width Height) Hit Box */
  158.    GADGHCOMP,        /* Flags */
  159.    RELVERIFY,        /* Activation flags */
  160.    STRGADGET,        /* Type */
  161.    (APTR)&StrBorder, /* pointer to Border Image */
  162.    NULL,             /* no pointer to SelectRender */
  163.    &EnglText,        /* pointer to GadgetText */
  164.    0,                /* no MutualExclude */
  165.    (APTR)&EnglInfo,  /* pointer to SpecialInfo */
  166.    0,                /* no ID */
  167.    NULL              /* no pointer to special data */
  168. };
  169.  
  170. /* Phonetic string gadget is where the program puts the
  171.  * translated string, necessating a call to RefreshGadgets(),
  172.  * and is where the user can type in Phonemes.
  173.  */
  174. UBYTE PhonBuffer[PSTRINGSIZE] =
  175.   "DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
  176. struct StringInfo PhonInfo = {
  177.    PhonBuffer,    /* pointer to input buffer */
  178.    UndoBuffer,    /* pointer to undo buffer */
  179.    0,             /* initial buffer position */
  180.    PSTRINGSIZE,   /* max number of chars, including NULL */
  181.    0, 0,          /* display, undo positions */
  182.    32,          /* number of chars (currently) in the buffer */
  183.    0, 0, 0,    /* position variables calculated by Intuition */
  184.    NULL,          /* no pointer to RastPort */
  185.    NULL,          /* not a LongInt string gadget */
  186.    NULL           /* no pointer to alternate keymap */
  187. };
  188. struct IntuiText PhonText = {
  189.    WHTP, BLUP,    /* FrontPen, BackPen */
  190.    JAM1,          /* DrawMode */
  191.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  192.    &TestFont,     /* pointer to TextFont */
  193.    "Phonetics:",  /* pointer to Text */
  194.    NULL           /* no pointer to NextText */
  195. };
  196. struct Gadget PhonStrGadget = {
  197.    &EnglStrGadget,   /* pointer to Next Gadget */
  198.    11, 94, 290, 10,  /* (Left Top Width Height) Hit Box */
  199.    GADGHCOMP,        /* Flags */
  200.    RELVERIFY,        /* Activation flags */
  201.    STRGADGET,        /* Type */
  202.    (APTR)&StrBorder, /* pointer to Border Image */
  203.    NULL,             /* no pointer to SelectRender */
  204.    &PhonText,        /* pointer to GadgetText */
  205.    0,                /* no MutualExclude */
  206.    (APTR)&PhonInfo,  /* pointer to SpecialInfo */
  207.    0,                /* no ID */
  208.    NULL              /* no pointer to special data */
  209. };
  210.  
  211. /* Now come the Boolean Gadgets.
  212.  * The female/male pair shows the simplest implementation I
  213.  * could think of to show how you can do mutual-exclude type
  214.  * things yourself. They are two toggle gadgets that use
  215.  * highlight image. The program starts with one selected, and
  216.  * then if either of them are hit, both toggle. Until either
  217.  * of them is hit again. Gadgets must be deleted and added
  218.  * whenever you want to change structure member values that
  219.  * intuition expects to be coming from the user, not a program
  220.  * (like the SELECTED bit in flags). Note that certain
  221.  * structure values CAN be changed programaticly without all
  222.  * this broohaha. Haha. Consult the intuition manual.
  223.  */
  224. /* Female Toggle (Highlight Image)
  225.    (Quasi mutual exclude with Male Toggle) */
  226. struct Image FemaleImage = {
  227.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  228.    20, 10, 1,  /* Width, Height, Depth */
  229.    NULL,       /* pointer to ImageData */
  230.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  231. };
  232. struct Gadget FemaleGadget = {
  233.    &PhonStrGadget,      /* pointer to Next Gadget */
  234.    134, 34, 20, 10,     /* (Left Top Width Height) Hit Box */
  235.    GADGIMAGE | GADGHCOMP,  /* Flags */
  236.    /* Activation flags */
  237.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  238.    BOOLGADGET,          /* Type */
  239.    (APTR)&FemaleImage,  /* pointer to GadgetRender */
  240.    NULL,                /* no pointer to SelectRender */
  241.    NULL,                /* no pointer to GadgetText */
  242.    0,                   /* no MutualExclude */
  243.    NULL,                /* no pointer to SpecialInfo */
  244.    0,                   /* no ID */
  245.    NULL                 /* no pointer to special data */
  246. };
  247.  
  248. /* Male Toggle (Highlight Image)
  249.    (Quasi mutual Exclude with above) */
  250. struct Image MaleImage = {
  251.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  252.    20, 10, 1,  /* Width, Height, Depth */
  253.    NULL,       /* pointer to ImageData */
  254.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  255. };
  256. struct Gadget MaleGadget = {
  257.    &FemaleGadget,    /* pointer to Next Gadget */
  258.    154, 34, 20, 10,  /* (Left Top Width Height) Hit Box */
  259.    GADGIMAGE | GADGHCOMP | SELECTED,   /* Flags */
  260.    /* Activation flags */
  261.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
  262.    BOOLGADGET,       /* Type */
  263.    (APTR)&MaleImage, /* pointer to GadgetRender */
  264.    NULL,             /* no pointer to SelectRender */
  265.    NULL,             /* no pointer to GadgetText */
  266.    0,                /* no MutualExclude */
  267.    NULL,             /* no pointer to SpecialInfo */
  268.    0,                /* no ID */
  269.    NULL              /* no pointer to special data */
  270. };
  271.  
  272. /* This boolean toggle gadget has an
  273.  * alternate image that indicates
  274.  * selection. The image stays flipped
  275.  * until it gets another hit. (it toggles)
  276.  */
  277. /* Inflection Mode Toggle (AltImage) *************************/
  278. struct Image HumanImage = {
  279.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  280.    40, 20, 1,  /* Width, Height, Depth */
  281.    NULL,       /* pointer to ImageData */
  282.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  283. };
  284. struct Image RobotImage = {
  285.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  286.    40, 20, 1,  /* Width, Height, Depth */
  287.    NULL,       /* pointer to ImageData */
  288.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  289. };
  290. struct Gadget ModeGadget = {
  291.    &MaleGadget,            /* pointer to Next Gadget */
  292.    134, 2, 40, 20,        /* (Left Top Width Height) Hit Box */
  293.    GADGIMAGE | GADGHIMAGE, /* Flags */
  294.    /* Activation flags */
  295.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  296.    BOOLGADGET,             /* Type */
  297.    (APTR)&HumanImage,      /* pointer to GadgetRender */
  298.    (APTR)&RobotImage,      /* pointer to SelectRender */
  299.    NULL,                   /* no pointer to GadgetText */
  300.    0,                      /* no MutualExclude */
  301.    NULL,                   /* no pointer to SpecialInfo */
  302.    0,                      /* no ID */
  303.    NULL                    /* no pointer to special data */
  304. };
  305.  
  306. /* Face Toggle (image and text) ******************************/
  307. struct IntuiText FaceIText = {
  308.    WHTP, BLUP, /* FrontPen, BackPen */
  309.    JAM2,       /* DrawMode */
  310.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  311.    &TestFont,  /* pointer to TextFont */
  312.    "Face",/* pointer to Text */
  313.    NULL        /* no pointer to NextText */
  314. };
  315. struct Image FaceImage = {
  316.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  317.    40, 10, 1,  /* Width, Height, Depth */
  318.    NULL,       /* pointer to ImageData */
  319.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  320. };
  321. struct Gadget FaceGadget = {
  322.    &ModeGadget,            /* pointer to Next Gadget */
  323.    134, 23, 40, 10,       /* (Left Top Width Height) Hit Box */
  324.    GADGIMAGE | GADGHCOMP,  /* Flags */
  325.    /* Activation flags */
  326.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  327.    BOOLGADGET,             /* Type */
  328.    (APTR) &FaceImage,      /* pointer to GadgetRender */
  329.    NULL,                   /* no pointer to SelectRender */
  330.    &FaceIText,             /* pointer to GadgetText */
  331.    0,                      /* no MutualExclude */
  332.    NULL,                   /* no pointer to SpecialInfo */
  333.    0,                      /* no ID */
  334.    NULL                    /* no pointer to special data */
  335. };
  336.  
  337. /* Stop Hit (image and text) ******************************/
  338. struct IntuiText StopIText = {
  339.    WHTP, BLUP, /* FrontPen, BackPen */
  340.    JAM2,       /* DrawMode */
  341.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  342.    &TestFont,  /* pointer to TextFont */
  343.    "Stop",/* pointer to Text */
  344.    NULL        /* no pointer to NextText */
  345. };
  346. struct Image StopImage = {
  347.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  348.    40, 10, 1,  /* Width, Height, Depth */
  349.    NULL,       /* pointer to ImageData */
  350.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  351. };
  352. struct Gadget StopGadget = {
  353.    &FaceGadget,            /* pointer to Next Gadget */
  354.    134, 45, 40, 10,        /* Left Top Width Height Hit Box */
  355.    GADGIMAGE | GADGHCOMP,  /* Flags */
  356.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  357.    BOOLGADGET,             /* Type */
  358.    (APTR) &StopImage,      /* pointer to GadgetRender */
  359.    NULL,                   /* no pointer to SelectRender */
  360.    &StopIText,             /* pointer to GadgetText */
  361.    0,                      /* no MutualExclude */
  362.    NULL,                   /* no pointer to SpecialInfo */
  363.    0,                      /* no ID */
  364.    NULL                    /* no pointer to special data */
  365. };
  366.  
  367. /* This is a hit (as opposed to toggle)
  368.    gadget that starts the translation.*/
  369. /* Translate Hit (Highlight image) ***************************/
  370. USHORT TransVectors[] = {
  371.    0, 0,    79, 0,    79, 13,   0, 13,
  372.    0, 1,    78, 1,    78, 12,   1, 12,
  373.    1, 1
  374. };
  375. struct Border TransBorder = {
  376.    -4, -3,           /* initial offsets, gadget relative */
  377.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  378.    9,                /* number of vectors */
  379.    TransVectors,     /* pointer to the array of vectors */
  380.    NULL              /* no next Border, can point to another */
  381. };
  382. struct IntuiText TranslateIText = {
  383.    WHTP, BLUP, /* FrontPen, BackPen */
  384.    JAM2,       /* DrawMode */
  385.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  386.    &TestFont,  /* pointer to TextFont */
  387.    "Translate",/* pointer to Text */
  388.    NULL        /* no pointer to NextText */
  389. };
  390. struct Gadget TranslateGadget = {
  391.    &StopGadget,      /* pointer to Next Gadget */
  392.    229, 48, 71, 8,   /* (Left Top Width Height) Hit Box */
  393.    GADGHCOMP,        /* Flags */
  394.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  395.    BOOLGADGET,       /* Type */
  396.    (APTR)&TransBorder,  /* no pointer to GadgetRender */
  397.    NULL,             /* no pointer to SelectRender */
  398.    &TranslateIText,  /* pointer to GadgetText */
  399.    0,                /* no MutualExclude */
  400.    NULL,             /* no pointer to SpecialInfo */
  401.    0,                /* no ID */
  402.    NULL              /* no pointer to special data */
  403. };
  404.  
  405. /* This is a hit (as opposed to toggle) Starts the narration */
  406. /* Speak Hit (Highlight Image) *******************************/
  407. USHORT SpeakVectors[] = {
  408.    0, 0,    47, 0,    47, 13,   0, 13,
  409.    0, 1,    46, 1,    46, 12,   1, 12,
  410.    1, 1
  411. };
  412. struct Border SpeakBorder = {
  413.    -4, -3,           /* initial offsets, gadget relative */
  414.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  415.    9,                /* number of vectors */
  416.    SpeakVectors,   /* pointer to the actual array of vectors */
  417.    NULL       /* no next Border, can point to another border */
  418. };
  419. struct IntuiText SpeakIText = {
  420.    WHTP, BLUP, /* FrontPen, BackPen */
  421.    JAM2,       /* DrawMode */
  422.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  423.    &TestFont,  /* pointer to TextFont */
  424.    "Speak",    /* pointer to Text */
  425.    NULL        /* no pointer to NextText */
  426. };
  427. struct Gadget SpeakGadget = {
  428.    &TranslateGadget, /* pointer to Next Gadget */
  429.    261, 79, 40, 8,   /* (Left Top Width Height) Hit Box */
  430.    GADGHCOMP,        /* Flags */
  431.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  432.    BOOLGADGET,       /* Type */
  433.    (APTR)&SpeakBorder,  /* pointer to GadgetRender */
  434.    NULL,             /* no pointer to SelectRender */
  435.    &SpeakIText,      /* pointer to GadgetText */
  436.    0,                /* no MutualExclude */
  437.    NULL,             /* no pointer to SpecialInfo */
  438.    0,                /* no ID */
  439.    NULL              /* no pointer to special data */
  440. };
  441.  
  442. /* Now the proportional gadgets. */
  443. /* Proportional Gadgets **************************************/
  444. /* The following variables are used to create proportional
  445.  * Gadgets. These variables will be filled in with copies of
  446.  * the generic Gadgetry below.
  447.  */
  448. SHORT PropCount = 0;       /* index to next available Gadget */
  449. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  450. /* dummy AUTOKNOB Images are required */
  451. struct Image PImages[NUMPROPS];
  452. /* These get copies of TPropInfo */
  453. struct PropInfo PInfos[NUMPROPS];
  454. /* These get copies of TPropGadget */
  455. struct Gadget Props[NUMPROPS];
  456. struct IntuiText TPropText = {
  457.    WHTP, BLUP,   /* FrontPen, BackPen */
  458.    JAM1,         /* DrawMode */
  459.    0, -10,       /* LeftEdge, TopEdge (relative to gadget) */
  460.    &TestFont,    /* pointer to TextFont */
  461.    NULL,         /* pointer to Text is filled at runtime */
  462.    NULL          /* no pointer to NextText */
  463. };   
  464. struct PropInfo TPropInfo = {
  465.    AUTOKNOB | FREEHORIZ,  /* Flags */
  466.    0, 0,            /* Pots:  Horiz, Vert: both start at 0 */
  467.    0x1FFF, 0x1FFF,  /* Bodies: Horiz is 1/8, Vert is 1/8 */
  468.    0, 0, 0, 0, 0, 0 /* System usage stuff */
  469. };
  470. /* this is the template for the Gadget of a horizontal */
  471. /* Proportional Gadget */
  472. struct Gadget TPropGadget = {
  473.    &SpeakGadget,              /* pointer to NextGadget */
  474.    7, 12, 115, 10,            /* Select Box L T W H */
  475.    GADGHCOMP | GADGIMAGE,     /* Flags */
  476.    GADGIMMEDIATE | RELVERIFY, /* Activation flags */
  477.    PROPGADGET,                /* Type */
  478.    NULL,       /* pointer to Image filled in later */
  479.    NULL,       /* no pointer to SelectRender */
  480.    NULL,       /* no pointer to GadgetText */
  481.    0,          /* no MutualExclude */
  482.    NULL,       /* SpecialInfo proportional data filled later */
  483.    0,          /* no ID */
  484.    NULL        /* no pointer to special data */
  485. };
  486.  
  487. struct IntuitionBase *IntuitionBase = 0;
  488. struct GfxBase *GfxBase = 0;
  489.  
  490. /* Only one menu. */
  491.  
  492. ULONG MenuNumber;
  493. ULONG TheMenu;
  494. ULONG TheItem;
  495.  
  496. struct IntuiText MenuItemText = {
  497.    BLUP,         /* Front Pen */
  498.    WHTP,         /* Back pen */
  499.    JAM2,         /* Draw Mode */
  500.    0,            /* Left Edge */
  501.    0,            /* Top */
  502.    &TestFont,    /* pointer to TextFont */
  503.    "About SpeechToy...", /* text */
  504.    NULL          /* next */
  505. };
  506. struct MenuItem MyMenuItem = {
  507.    NULL,                /* pointer to next item */
  508.    0,                   /* left */
  509.    0,                   /* top */
  510.    150,                 /* width */
  511.    8,                   /* height */
  512.    ITEMTEXT | ITEMENABLED | HIGHCOMP,  /* flags */
  513.    0,                   /* no mutual exclude */
  514.    (APTR)&MenuItemText, /* Render */
  515.    NULL,                /* pointer to alternate image */
  516.    NULL,                /* Command "amiga" char */
  517.    NULL,                /* Sub Item */
  518.    MENUNULL             /* nextselect */
  519. };
  520.  
  521. struct Menu MyMenu = {
  522.    NULL,          /* pointer to next menu */
  523.    0,0,150,0,     /* left,0,Width,0 */
  524.    MENUENABLED,   /* flags */
  525.    "SpeachToy Menu",   /* menu name */
  526.    &MyMenuItem    /* First Item in list */
  527. };
  528.  
  529. struct IntuiText ReqText1 = {
  530.    BLUP,         /* Front Pen */
  531.    WHTP,         /* Back pen */
  532.    JAM2,         /* Draw Mode */
  533.    5,            /* Left Edge */
  534.    23,           /* Top */
  535.    &TestFont,    /* pointer to TextFont */
  536.    "Version 1.1   8 Dec, 1985",  /* text */
  537.    NULL          /* next */
  538. };
  539. struct IntuiText ReqText2 = {
  540.    BLUP,         /* Front Pen */
  541.    WHTP,         /* Back pen */
  542.    JAM2,         /* Draw Mode */
  543.    5,            /* Left Edge */
  544.    13,           /* Top */
  545.    &TestFont,    /* pointer to TextFont */
  546.    "Freeware - Public Domain ", /* text */
  547.    &ReqText1     /* next */
  548. };
  549. struct IntuiText ReqText3 = {
  550.    BLUP,         /* Front Pen */
  551.    WHTP,         /* Back pen */
  552.    JAM2,         /* Draw Mode */
  553.    5,            /* Left Edge */
  554.    3,            /* Top */
  555.    &TestFont,    /* pointer to TextFont */
  556.    "Written by David M Lucas ", /* text */
  557.    &ReqText2     /* next */
  558. };
  559.  
  560. struct IntuiText OKIText = {
  561.    BLUP, WHTP, /* FrontPen, BackPen */
  562.    JAM2,       /* DrawMode */
  563.    6, 3,       /* LeftEdge, TopEdge (relative to gadget) */
  564.    &TestFont,  /* pointer to TextFont */
  565.    "OK",       /* pointer to Text */
  566.    NULL        /* no pointer to NextText */
  567. };
  568.  
  569. struct Requester *AboutRequester;
  570.  
  571. USHORT autoret;
  572. struct Window *ControlWindow = NULL;
  573. struct Window *FaceWindow = NULL;
  574. struct IntuiMessage *MyIntuiMessage;
  575. struct NewWindow NewControlWindow = {
  576.    00, 11,                    /* start LeftEdge, TopEdge */
  577.    CONTWINDW, CONTWINDH,      /* start Width, Height */
  578.    -1, -1,                    /* DetailPen, BlockPen */
  579.    GADGETUP | CLOSEWINDOW | MENUPICK,  /* IDCMP FLAGS */
  580.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  581.    | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */
  582.    &Props[NUMPROPS-1],        /* Pointer to FirstGadget */
  583.    NULL,                    /* no pointer to first CheckMark */
  584.    "SpeechToy",               /* Title (can be NULL) */
  585.    NULL,                      /* no Pointer to Screen */
  586.    NULL,                      /* no Pointer to BitMap */
  587.    20, 20,                    /* Min/max  Sizable to (w/h) */
  588.    CONTWINDW, CONTWINDH,      /* These aint used, can't size */
  589.    WBENCHSCREEN         /* Type of screen window appears in */
  590. };
  591.  
  592. struct NewWindow NewFaceWindow = {
  593.    CONTWINDW, 11,             /* start LeftEdge, TopEdge */
  594.    FACEWINDW * 2, FACEWINDH,  /* start Width, Height */
  595.    -1, -1,                    /* DetailPen, BlockPen */
  596.    SIZEVERIFY | NEWSIZE,      /* IDCMP FLAGS */
  597.    /* Flags (can be NULL) */
  598.    WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
  599.     | SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
  600.    NULL,                /* no Pointer to FirstGadget */
  601.    NULL,                /* no Pointer to first CheckMark */
  602.    "Face",              /* Title */
  603.    NULL,                /* no Pointer to Screen */
  604.    NULL,                /* no Pointer to BitMap */
  605.    FACEWINDW, FACEWINDH,/* Minimum sizeable to */
  606.    640, 200,            /* Maximum sizeable to */
  607.    WBENCHSCREEN         /* Type of screen window appears in */
  608. };
  609.  
  610. USHORT FemaleIData[] = {
  611. /*   ----    -  These nibbles matter to image. */
  612.    0x0000, 0x0000,
  613.    0x00F0, 0x0000,
  614.    0x0198, 0x0000,
  615.    0x030C, 0x0000,
  616.    0x0198, 0x0000,
  617.    0x00F0, 0x0000,
  618.    0x0060, 0x0000,
  619.    0x01F8, 0x0000,
  620.    0x0060, 0x0000,
  621.    0x0000, 0x0000
  622. };
  623.  
  624. USHORT MaleIData[] = {
  625. /*   ----    -   These nibbles matter to image. */
  626.    0x0000, 0x0000,
  627.    0x003E, 0x0000,
  628.    0x000E, 0x0000,
  629.    0x0036, 0x0000,
  630.    0x01E0, 0x0000,
  631.    0x0330, 0x0000,
  632.    0x0618, 0x0000,
  633.    0x0330, 0x0000,
  634.    0x01E0, 0x0000,
  635.    0x0000, 0x0000
  636. };
  637. USHORT HumanIData[] = {
  638. /*   ----   ----   --   These nibbles matter to image. */
  639.    0x0000,0x0000,0x0000,
  640.    0x0000,0x0000,0x0000,
  641.    0x0000,0x0000,0x0000,
  642.    0x0000,0x0000,0x0000,
  643.    0x0007,0x9E00,0x0000,
  644.    0x0001,0x8600,0x0000,
  645.    0x0000,0x0000,0x0000,
  646.    0x0000,0x0000,0x0000,
  647.    0x0000,0x2000,0x0000,
  648.    0x0000,0x1000,0x0000,
  649.    0x0000,0x0800,0x0000,
  650.    0x0000,0x7C00,0x0000,
  651.    0x0000,0x0000,0x0000,
  652.    0x0000,0x0000,0x0000,
  653.    0x0000,0x0000,0x0000,
  654.    0x0000,0x7800,0x0000,
  655.    0x0000,0x0000,0x0000,
  656.    0x0000,0x0000,0x0000,
  657.    0x0000,0x0000,0x0000,
  658.    0x0000,0x0000,0x0000
  659. };
  660. USHORT RobotIData[] = {
  661. /*   ----   ----   --   These nibbles matter to image. */
  662.    0x0000,0x0000,0x0000,
  663.    0x0000,0x0000,0x0000,
  664.    0x0000,0x0000,0x0000,
  665.    0x0000,0x0000,0x0000,
  666.    0x0007,0x9E00,0x0000,
  667.    0x0004,0x9200,0x0000,
  668.    0x0007,0x9E00,0x0000,
  669.    0x0000,0x0000,0x0000,
  670.    0x0000,0x0000,0x0000,
  671.    0x0000,0x0000,0x0000,
  672.    0x0000,0x0000,0x0000,
  673.    0x0000,0x0000,0x0000,
  674.    0x0000,0x0000,0x0000,
  675.    0x0001,0xF800,0x0000,
  676.    0x0001,0x0800,0x0000,
  677.    0x0001,0xF800,0x0000,
  678.    0x0000,0x0000,0x0000,
  679.    0x0000,0x0000,0x0000,
  680.    0x0000,0x0000,0x0000,
  681.    0x0000,0x0000,0x0000
  682. };
  683. USHORT FaceIData[] = {
  684. /*   ----   ----   --   These nibbles matter to image. */
  685.    0x0000,0x0000,0x0000,
  686.    0x0000,0x0000,0x0000,
  687.    0x0000,0x0000,0x0000,
  688.    0x0000,0x0000,0x0000,
  689.    0x0000,0x0000,0x0000,
  690.    0x0000,0x0000,0x0000,
  691.    0x0000,0x0000,0x0000,
  692.    0x0000,0x0000,0x0000,
  693.    0x0000,0x0000,0x0000,
  694.    0x0000,0x0000,0x0000
  695. };
  696. USHORT StopIData[] = {
  697. /*   ----   ----   --   These nibbles matter to image. */
  698.    0x0000,0x0000,0x0000,
  699.    0x0000,0x0000,0x0000,
  700.    0x0000,0x0000,0x0000,
  701.    0x0000,0x0000,0x0000,
  702.    0x0000,0x0000,0x0000,
  703.    0x0000,0x0000,0x0000,
  704.    0x0000,0x0000,0x0000,
  705.    0x0000,0x0000,0x0000,
  706.    0x0000,0x0000,0x0000,
  707.    0x0000,0x0000,0x0000
  708. };
  709. USHORT *FemaleIData_chip = 0;
  710. USHORT *MaleIData_chip = 0;
  711. USHORT *HumanIData_chip = 0;
  712. USHORT *RobotIData_chip = 0;
  713. USHORT *FaceIData_chip = 0;
  714. USHORT *StopIData_chip = 0;
  715.  
  716. /** start of code ***************************/
  717. main()
  718. {
  719.    ULONG Signals;        /* Wait() tells me which to look at */
  720.    ULONG MIClass;        /* Save quickly, ReplyMsg() asap */
  721.    USHORT MICode;        /* These hold my needed information */
  722.    APTR MIAddress;
  723.  
  724.    /* let MyCleanup know these signals not allocated yet */
  725.    talk_port.mp_SigBit = -1;
  726.    read_port.mp_SigBit = -1;
  727.  
  728.    /* Open those libraries that the program uses directly */
  729.    if ((IntuitionBase = (struct IntuitionBase *)
  730.     OpenLibrary("intuition.library", REVISION)) == 0) {
  731. #ifdef DEBUG
  732.       printf("Can't open the intuition library\n");
  733. #endif
  734.       MyCleanup();
  735.       exit(FALSE);
  736.    }
  737.  
  738.    if ((GfxBase = (struct GfxBase *)
  739.     OpenLibrary("graphics.library", REVISION)) == 0) {
  740. #ifdef DEBUG
  741.       printf("Can't open the graphics library\n");
  742. #endif
  743.       MyCleanup();
  744.       exit(FALSE);
  745.    }
  746.  
  747.    if ((TranslatorBase = (struct Library *)
  748.     OpenLibrary("translator.library", REVISION)) == 0) {
  749. #ifdef DEBUG
  750.       printf("Can't open the translator library\n");
  751. #endif
  752.       MyCleanup();
  753.       exit(FALSE);
  754.    }
  755.  
  756.    /* Open the device */
  757.    if ((NarratorOpenError = OpenDevice("narrator.device", 0,
  758.     &voice_io, 0)) != 0) {
  759. #ifdef DEBUG
  760.       printf("Can't open the narrator device\n");
  761. #endif
  762.       MyCleanup();
  763.       exit(FALSE);
  764.    }
  765.    /* This is where the proportional gadgets are set up, using
  766.     * the templates that were declared staticly.
  767.     */
  768.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  769.       PTexts[PropCount] = TPropText;
  770.       Props[PropCount] = TPropGadget;
  771.       PInfos[PropCount] = TPropInfo;
  772.       Props[PropCount].GadgetText = (struct IntuiText *)
  773.        &PTexts[PropCount];
  774.       Props[PropCount].GadgetRender = (APTR)
  775.        &PImages[PropCount];
  776.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  777.       switch (PropCount) {
  778.       case 0:
  779.          PTexts[PropCount].IText = "Sample Freq:";
  780.          if (DEFFREQ == MAXFREQ)
  781.             PInfos[PropCount].HorizPot = 65535;
  782.          else
  783.             PInfos[PropCount].HorizPot = ((DEFFREQ - MINFREQ)
  784.              << 16) / (MAXFREQ - MINFREQ);
  785.          break;
  786.       case 1:
  787.          PTexts[PropCount].IText = "Rate:";
  788.          Props[PropCount].TopEdge += 22;
  789.          Props[PropCount].NextGadget = &Props[PropCount-1];
  790.          if (DEFRATE == MAXRATE)
  791.             PInfos[PropCount].HorizPot = 65535;
  792.          else
  793.             PInfos[PropCount].HorizPot = ((DEFRATE - MINRATE)
  794.              << 16) / (MAXRATE - MINRATE);
  795.          break;
  796.       case 2:
  797.          PTexts[PropCount].IText = "Pitch:";
  798.          Props[PropCount].LeftEdge += 183;
  799.          Props[PropCount].NextGadget = &Props[PropCount-1];
  800.          if (DEFPITCH == MAXPITCH)
  801.             PInfos[PropCount].HorizPot = 65535;
  802.          else
  803.             PInfos[PropCount].HorizPot = ((DEFPITCH-MINPITCH)
  804.              << 16) / (MAXPITCH - MINPITCH);
  805.          break;
  806.       case 3:
  807.          PTexts[PropCount].IText = "Volume:";
  808.          Props[PropCount].TopEdge += 22;
  809.          Props[PropCount].LeftEdge += 183;
  810.          Props[PropCount].NextGadget = &Props[PropCount-1];
  811.          if (DEFVOL == MAXVOL)
  812.             PInfos[PropCount].HorizPot = 65535;
  813.          else
  814.             PInfos[PropCount].HorizPot = ((DEFVOL - MINVOL)
  815.              << 16) / (MAXVOL - MINVOL);
  816.          break;
  817. /* the following for lattice bug */
  818. /* it likes 1,2,3,5.. but not 4 in a switch */
  819.       case 4: break;
  820.       }
  821.    }
  822.  
  823.    /* Now allocate memory accessable by the chips for images */
  824.    if (InitImages() != TRUE) {
  825. #ifdef DEBUG
  826.       printf("Couldn't Allocate Images in chip memory.\n");
  827. #endif
  828.       MyCleanup();
  829.       exit(FALSE);
  830.    }
  831.  
  832.    /* Set up the write port, allocate the signal, */
  833.    /* and the message */
  834.    talk_port.mp_Node.ln_Type = NT_MSGPORT;
  835.    talk_port.mp_Flags = 0;
  836.    if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
  837. #ifdef DEBUG
  838.       printf("Couldn't Allocate talk Signal bit\n");
  839. #endif
  840.       MyCleanup();
  841.       exit(FALSE);
  842.    }
  843.    talk_port.mp_SigTask = (struct Task *) FindTask((char *)
  844.     NULL);
  845.    NewList(&talk_port.mp_MsgList);
  846.  
  847.    /* Set up the read port, allocate the signal, */
  848.    /*  and the message */
  849.    read_port.mp_Node.ln_Type = NT_MSGPORT;
  850.    read_port.mp_Flags = 0;
  851.    if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
  852. #ifdef DEBUG
  853.       printf("Couldn't Allocate read Signal bit\n");
  854. #endif
  855.       MyCleanup();
  856.       exit(FALSE);
  857.    }
  858.    read_port.mp_SigTask = (struct Task *)
  859.     FindTask((char *) NULL);
  860.    NewList(&read_port.mp_MsgList);
  861.  
  862.    /* Set up the write channel information */
  863.    voice_io.ch_masks = (audio_chan);
  864.    voice_io.nm_masks = sizeof(audio_chan);
  865.    voice_io.mouths = 0;
  866.    voice_io.message.io_Message.mn_ReplyPort = &talk_port;
  867.    voice_io.message.io_Command = CMD_WRITE;
  868.    voice_io.message.io_Offset = 0;
  869.    voice_io.message.io_Data = (APTR)PhonBuffer;
  870.    voice_io.message.io_Message.mn_Length = sizeof(voice_io);
  871.  
  872.   /* Set up the read channel information */
  873.    mouth_io.voice = voice_io;
  874.    mouth_io.width = 0;
  875.    mouth_io.height = 0;
  876.    mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
  877.    mouth_io.voice.message.io_Command = CMD_READ;
  878.    mouth_io.voice.message.io_Error = 0;
  879.    if (FaceWindow == NULL) {
  880.       if ((ControlWindow = (struct Window *)OpenWindow
  881.        (&NewControlWindow)) == NULL) {
  882. #ifdef DEBUG
  883.          printf("Couldn't open the control window.\n");
  884. #endif
  885.          MyCleanup();
  886.          exit(FALSE);
  887.       }
  888.    }
  889.  
  890.    /* fill background of window */
  891.    SetAPen(ControlWindow->RPort, BLKP);
  892.    RectFill(ControlWindow->RPort,0,0,
  893.     ControlWindow->GZZWidth, ControlWindow->GZZHeight);
  894.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  895.  
  896.    SetMenuStrip(ControlWindow, &MyMenu);
  897.  
  898. /* !!! Ah, But what if FaceWindow's not been opened? */
  899.    for (;;) {  /* ever wait for a signal and process it */
  900.       /* wait lets the rest of the system run, */
  901.       /* this program sleeps */
  902.       Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
  903. | (1 << FaceWindow->UserPort->mp_SigBit)
  904. | (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
  905. | (1 <<
  906.    mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit));
  907.       /* now check to see to what we owe the intrusion */
  908.  
  909.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  910.          /* Process the Intuition message */
  911.          while (MyIntuiMessage=(struct IntuiMessage *)
  912.                       GetMsg(ControlWindow->UserPort)) {
  913.             /* Get all the needed info and give message back */
  914.             MIClass = MyIntuiMessage->Class;
  915.             MICode = MyIntuiMessage->Code;
  916.             MIAddress = MyIntuiMessage->IAddress;
  917.             ReplyMsg(MyIntuiMessage);
  918.             /* Now, what was it you wanted? */
  919.             switch (MIClass) {
  920.                case MENUPICK:
  921.                   menumessage(MICode, ControlWindow);
  922.                   break;
  923.                case GADGETUP:         /* reply, then process */
  924.                   gadgetmessage(MIAddress, ControlWindow);
  925.                   break;
  926.                case CLOSEWINDOW:       /* bye! */
  927.                   while (MyIntuiMessage = (struct
  928.                    IntuiMessage *) GetMsg(
  929.                    ControlWindow->UserPort))
  930.                     ReplyMsg(MyIntuiMessage);
  931.                   MyCleanup();
  932.                   exit(TRUE);
  933.                   break;
  934.                default:
  935. #ifdef DEBUG
  936.                   printf("Unhandled Message Received.\n");
  937. #endif
  938.                   break;
  939.             }  /* switch */
  940.          } /* while */
  941.       } /* if */
  942.  
  943.  
  944.       /* Woken by intuition for FaceWindow*/
  945.       if (Signals & (1<< FaceWindow->UserPort->mp_SigBit)) {
  946.          /* Process the Intuition message */
  947.          while (MyIntuiMessage=(struct IntuiMessage *)
  948.           GetMsg(FaceWindow->UserPort)) {
  949.             switch (MyIntuiMessage->Class) {
  950.                case SIZEVERIFY:
  951.                   ReplyMsg(MyIntuiMessage);
  952.                   break;
  953.                case NEWSIZE:  /* Don't reply until processed */
  954.                   DrawFace();
  955.                   ReplyMsg(MyIntuiMessage);
  956.                   break;
  957.                default:
  958. #ifdef DEBUG
  959.                   printf("Unhandled Message Received.\n");
  960. #endif
  961.                   ReplyMsg(MyIntuiMessage);
  962.                   break;
  963.             }  /* switch */
  964.          } /* while */
  965.       } /* if */
  966.  
  967.       /* A voice SendIO (Write) has completed */
  968.       if (Signals & (1 <<
  969.        voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  970.          /* Was it Sucessful? filter out the abort error */
  971.          if (voice_io.message.io_Error == -2)
  972.             voice_io.message.io_Error = 0;
  973.          if (voice_io.message.io_Error != 0) {
  974. #ifdef DEBUG
  975.             printf("Narrator won't. (%ld)\n",
  976.              voice_io.message.io_Error);
  977. #endif
  978.             /* flash this screen */
  979.             DisplayBeep(ControlWindow->WScreen);
  980.             /* let user see where phoneme string was bad. */
  981.             i = RemoveGadget(ControlWindow, &PhonStrGadget);
  982.             /* move the cursor to the error char */
  983.             PhonInfo.BufferPos = voice_io.message.io_Actual -1;
  984.             /* assure cursor (error point) is shown in gad. */
  985.             /* within 29 (number of chars shown) of front */
  986.             if (voice_io.message.io_Actual < 29)
  987.                PhonInfo.DispPos = 0;
  988.             /* within 29 of end */
  989.             else if ((voice_io.message.io_Length -
  990.                       voice_io.message.io_Actual) < 29)
  991.                PhonInfo.DispPos = voice_io.message.io_Length
  992.                                   - 29;
  993.             else
  994.                PhonInfo.DispPos = voice_io.message.io_Actual
  995.                                   - 15;
  996.             AddGadget(ControlWindow, &PhonStrGadget, i);
  997.             RefreshGadgets(&PhonStrGadget, ControlWindow,
  998.              NULL);
  999.             voice_io.message.io_Error = 0;
  1000.          }
  1001.          SpeakGadget.Flags ^= GADGDISABLED;
  1002.          FaceGadget.Flags ^= GADGDISABLED;
  1003.       }
  1004.  
  1005.       /* A mouth DoIO (Read) has completed */
  1006.       if (Signals & (1 <<
  1007.   mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1008.          WaitBOVP(&FaceWindow->WScreen->ViewPort);
  1009.          SetAPen(FaceWindow->RPort, WHTP);
  1010.          RectFill(FaceWindow->RPort, 0, EyesBottom,
  1011.           FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1012.          if (MouthWMult == 0)
  1013.             LipWidth = mouth_io.width >> 1;
  1014.          else
  1015.             LipWidth = mouth_io.width * MouthWMult;
  1016.          if (MouthHMult == 0)
  1017.             LipHeight = mouth_io.height >> 1;
  1018.          else
  1019.             LipHeight = mouth_io.height * (MouthHMult);
  1020.          SetAPen(FaceWindow->RPort, REDP);
  1021.          Move(FaceWindow->RPort,
  1022.           XMouthCenter - LipWidth, YMouthCenter);
  1023.          Draw(FaceWindow->RPort,
  1024.           XMouthCenter, YMouthCenter - LipHeight);
  1025.          Draw(FaceWindow->RPort,
  1026.           XMouthCenter + LipWidth, YMouthCenter);
  1027.          Draw(FaceWindow->RPort,
  1028.           XMouthCenter, YMouthCenter + LipHeight);
  1029.          Draw(FaceWindow->RPort,
  1030.           XMouthCenter - LipWidth, YMouthCenter);
  1031.          /* the narrator will give an error when the */
  1032.          /* write has completed and I've tried to read */
  1033.          /* so I stop trying when that happens */
  1034.          if (mouth_io.voice.message.io_Error == 0)
  1035.             SendIO(&mouth_io);
  1036.       }
  1037.    }  /* for */
  1038. }  /* main */
  1039.  
  1040. /* a MENUPICK has been received, this
  1041.  * routine takes the appropriate action
  1042.  */
  1043. menumessage(code, w)
  1044. USHORT code;
  1045. struct Window *w;
  1046. {
  1047.    switch (MENUNUM(code)) {
  1048.       case 0:
  1049.          switch (ITEMNUM(code)) {
  1050.             case 0:
  1051.                AutoRequest(w, &ReqText3, NULL,
  1052.                            &OKIText, 0, 0, 280, 47);
  1053.                break;
  1054.          }
  1055.       break;
  1056.    }
  1057. }
  1058.  
  1059. /* a GADGETUP has been received, this
  1060.  * routine takes the appropriate action
  1061.  */
  1062. gadgetmessage(address, w)
  1063. APTR address;
  1064. struct Window *w;
  1065. {
  1066.    USHORT i;
  1067.    long PropRange;
  1068.    if (address == (APTR)&ModeGadget) {
  1069.       if (ModeGadget.Flags & SELECTED)
  1070.          voice_io.mode = ROBOTICF0;
  1071.       else
  1072.          voice_io.mode = NATURALF0;
  1073.    }
  1074.    else if (address == (APTR)&FaceGadget) {
  1075.       /* tell the write that reads will be forthcomming */
  1076.       if (FaceGadget.Flags & SELECTED) {
  1077.          voice_io.mouths = 1;
  1078.          if ((FaceWindow = (struct Window *)
  1079.           OpenWindow(&NewFaceWindow)) == NULL) {
  1080. #ifdef DEBUG
  1081.             printf("Couldn't open the face window.\n");
  1082. #endif
  1083.             MyCleanup();
  1084.             exit(FALSE);
  1085.          }
  1086.          SetMenuStrip(FaceWindow, &MyMenu);
  1087.          DrawFace();
  1088.       }
  1089.       else { /* FaceGadget de-SELECTed */
  1090.          voice_io.mouths = 0;
  1091.          NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
  1092.          NewFaceWindow.TopEdge = FaceWindow->TopEdge;
  1093.          NewFaceWindow.Width = FaceWindow->Width;
  1094.          NewFaceWindow.Height = FaceWindow->Height;
  1095.          CloseWindow(FaceWindow);
  1096.          FaceWindow = NULL;
  1097.       }
  1098.    }
  1099.    else if (address == (APTR)&StopGadget) {
  1100.       AbortIO(&voice_io);
  1101.       voice_io.message.io_Error = 0;
  1102.       mouth_io.voice.message.io_Error = 0;
  1103.    }
  1104.    /* Since this program changes a flag that intuition expects
  1105.     * only the user to change (SELECTED bit), this program has
  1106.     * to remove, then change, then add this gadget. Then by
  1107.     * passing the address of this gadget to RefreshGadgets(),
  1108.     * only the gadgets from here to the start of the list will
  1109.     * be refreshed, which minimizes the visible flash that
  1110.     * RefreshGadgets() can introduce.
  1111.     * If one of the two gadgets (female/male) is hit, toggle
  1112.     * the selection of the other gadget (since the gadget hit
  1113.     * was toggled by intuition when it was hit).
  1114.     */
  1115.    else if (address == (APTR)&FemaleGadget) {
  1116.       if (FemaleGadget.Flags & SELECTED)
  1117.       voice_io.sex = FEMALE;
  1118.       else
  1119.       voice_io.sex = MALE;
  1120.       i = RemoveGadget(ControlWindow, &MaleGadget);
  1121.       MaleGadget.Flags ^= SELECTED;
  1122.       AddGadget(ControlWindow, &MaleGadget, i);
  1123.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1124.    }
  1125.    else if (address == (APTR)&MaleGadget) {
  1126.       if (MaleGadget.Flags & SELECTED)
  1127.       voice_io.sex = MALE;
  1128.       else
  1129.       voice_io.sex = FEMALE;
  1130.       i = RemoveGadget(ControlWindow, &FemaleGadget);
  1131.       FemaleGadget.Flags ^= SELECTED;
  1132.       AddGadget(ControlWindow, &FemaleGadget, i);
  1133.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1134.    }
  1135.    /* Since the program changes the contents of the string
  1136.     * gadgets' buffer and it's size, which is something else
  1137.     * intuition doesn't expect a program (as opposed to the
  1138.     * user) to do. The program must remove, then change, then
  1139.     * add this gadget, and then by passing the address of this
  1140.     * gadget to RefreshGadgets(), only the gadgets from here
  1141.     * to the start of the list will be refreshed, which
  1142.     * minimizes the visible flash that RefreshGadgets() can
  1143.     * introduce.
  1144.     */
  1145.    else if (address == (APTR)&TranslateGadget) {
  1146.       i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1147.       if ((TranslatorError = Translate((APTR)EnglBuffer,
  1148.        EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
  1149.        != 0) {
  1150. #ifdef DEBUG
  1151.          printf("Translator won't. (%lx)\n",TranslatorError);
  1152. #endif
  1153.          /* flash this screen */
  1154.          DisplayBeep(ControlWindow->WScreen);
  1155.       }
  1156.       /* Hey! NumChars includes the terminating NULL. */
  1157.       /* This must be done. */
  1158.       PhonInfo.NumChars = voice_io.message.io_Length + 1;
  1159.       if (PhonInfo.DispPos > voice_io.message.io_Length)
  1160.           PhonInfo.DispPos = voice_io.message.io_Length;
  1161.       AddGadget(ControlWindow, &PhonStrGadget, i);
  1162.       RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
  1163.    }
  1164.    else if (address == (APTR)&SpeakGadget) {
  1165.       SpeakGadget.Flags ^= GADGDISABLED;
  1166.       FaceGadget.Flags ^= GADGDISABLED;
  1167.       voice_io.message.io_Length = strlen(PhonBuffer);
  1168.       SendIO(&voice_io);
  1169.       if (voice_io.mouths == 1) {
  1170.          mouth_io.voice.message.io_Error = 0;
  1171.          SendIO(&mouth_io);
  1172.       }
  1173.    }
  1174.    else if (address == (APTR)&EnglStrGadget);  /* do nothing */
  1175.    else if (address == (APTR)&PhonStrGadget);  /* do nothing */
  1176.    else if (address == (APTR)&Props[0]) {
  1177.       PropRange = RNGFREQ;
  1178.       voice_io.sampfreq = (( (PInfos[0].HorizPot >> 1)
  1179.        * PropRange) >> 15) + MINFREQ;
  1180. #ifdef DEBUG
  1181.       printf("Freq. = %ld\n", voice_io.sampfreq);
  1182. #endif
  1183.    }
  1184.    else if (address == (APTR)&Props[1]) {
  1185.       PropRange = RNGRATE;
  1186.       voice_io.rate = (((PInfos[1].HorizPot >> 1)
  1187.        * PropRange) >> 15) + MINRATE;
  1188. #ifdef DEBUG
  1189.       printf("Rate  = %ld\n", voice_io.rate);
  1190. #endif
  1191.    }
  1192.    else if (address == (APTR)&Props[2]) {
  1193.       PropRange = RNGPITCH;
  1194.       voice_io.pitch = (((PInfos[2].HorizPot >> 1)
  1195.        * PropRange) >> 15) + MINPITCH;
  1196. #ifdef DEBUG
  1197.       printf("Pitch = %ld\n", voice_io.pitch);
  1198. #endif
  1199.    }
  1200.    else if (address == (APTR)&Props[3]) {
  1201.       PropRange = RNGVOL;
  1202.       voice_io.volume = (((PInfos[3].HorizPot >> 1)
  1203.        * PropRange) >> 15) + MINVOL;
  1204. #ifdef DEBUG
  1205.       printf("Vol.  = %ld\n", voice_io.volume);
  1206. #endif
  1207.    }
  1208. #ifdef DEBUG
  1209.    else printf("Unhandled gadget up received!\n");
  1210. #endif
  1211. }
  1212.  
  1213. /* This calculates variables used to draw the mouth
  1214.  * and eyes, as well as redrawing the face.
  1215.  * Proportionality makes it very wierd, but it's
  1216.  * wierder if you don't use a GimmeZeroZero window
  1217.  * and GZZWidth/GZZHeight.
  1218.  */
  1219. DrawFace() {
  1220.    XMouthCenter =  FaceWindow->GZZWidth >> 1;
  1221.    /* set left edge of left eye */
  1222.    EyesLeft = FaceWindow->GZZWidth >> 2;
  1223.    /* multiplier for mouth width */
  1224.    MouthWMult = FaceWindow->GZZWidth >> 6;
  1225.  
  1226.    EyesTop = (FaceWindow->GZZHeight >> 2)
  1227.     - (FaceWindow->GZZHeight >> 4);
  1228.    EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
  1229.    yaw = FaceWindow->GZZHeight - EyesBottom;
  1230.    YMouthCenter = ((yaw >> 1) + EyesBottom);
  1231.    MouthHMult = yaw >> 5;
  1232.  
  1233.    /* Set pen to White */
  1234.    SetAPen(FaceWindow->RPort, WHTP);
  1235.    RectFill(FaceWindow->RPort, 0, 0,
  1236.     FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1237.  
  1238.    /* Set pen to Blue */
  1239.    SetAPen(FaceWindow->RPort, BLUP);
  1240.    RectFill(FaceWindow->RPort,
  1241.     EyesLeft, EyesTop,
  1242.     EyesLeft + (FaceWindow->GZZWidth >> 3),
  1243.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1244.    RectFill(FaceWindow->RPort,
  1245.     (FaceWindow->GZZWidth >> 1)
  1246.     + (FaceWindow->GZZWidth >> 3),
  1247.     EyesTop,
  1248.     (FaceWindow->GZZWidth >> 1)
  1249.      + (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
  1250.      + (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
  1251.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1252.  
  1253.     SetAPen(FaceWindow->RPort, REDP);  /* Set pen to Red */
  1254.     Move(FaceWindow->RPort,
  1255.      XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1256.     Draw(FaceWindow->RPort,
  1257.      XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1258.  
  1259. }
  1260.  
  1261. /* Deallocate any memory, and close all of the
  1262.  * windows/screens/devices/libraries in reverse order to
  1263.  * make things work smoothly. And be sure to check
  1264.  * that the open/allocation was successful before
  1265.  * closing/deallocating.
  1266.  */
  1267. MyCleanup()
  1268. {
  1269.    if (read_port.mp_SigBit != -1)
  1270.       FreeSignal(read_port.mp_SigBit);
  1271.    if (talk_port.mp_SigBit != -1)
  1272.       FreeSignal(talk_port.mp_SigBit);
  1273.    if (FaceWindow != NULL)
  1274.       CloseWindow(FaceWindow);
  1275.    if (ControlWindow != NULL)
  1276.       CloseWindow(ControlWindow);
  1277.    /* freeimages makes sure image allocation was successful */
  1278.    freeimages();
  1279.    if (NarratorOpenError == 0)
  1280.       CloseDevice(&voice_io);
  1281.    if (TranslatorBase != 0)
  1282.       CloseLibrary(TranslatorBase);
  1283.    if (GfxBase != 0)
  1284.       CloseLibrary(GfxBase);
  1285.    if (IntuitionBase != 0)
  1286.       CloseLibrary(IntuitionBase);
  1287.    return(0);
  1288. }
  1289.  
  1290. /* Allocate chip memory for gadget images, and set the
  1291.  * pointers in the corresponding image structures to point
  1292.  * to these images. This must be done because the program
  1293.  * could be loaded into expansion memory (off the side of
  1294.  * the box), which the custom chips cannot access.
  1295.  * And images must be in chip ram (that's memory that the
  1296.  * custom chips can access, the internal 512K).
  1297.  */
  1298. InitImages()
  1299. {
  1300.    /* the images were staticly initialized above main */
  1301.    extern USHORT *FemaleIData_chip;
  1302.    extern USHORT *MaleIData_chip;
  1303.    extern USHORT *HumanIData_chip;
  1304.    extern USHORT *RobotIData_chip;
  1305.    extern USHORT *FaceIData_chip;
  1306.    extern USHORT *StopIData_chip;
  1307.    int i;
  1308.  
  1309.    /* Allocate them all, stop and return false on failure */
  1310.    if ((FemaleIData_chip = (USHORT *)
  1311.     AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
  1312.       return(FALSE);
  1313.    if ((MaleIData_chip = (USHORT *)
  1314.     AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
  1315.       return(FALSE);
  1316.    if ((HumanIData_chip = (USHORT *)
  1317.     AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
  1318.       return(FALSE);
  1319.    if ((RobotIData_chip = (USHORT *)
  1320.     AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
  1321.       return(FALSE);
  1322.    if ((FaceIData_chip = (USHORT *)
  1323.     AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
  1324.       return(FALSE);
  1325.    if ((StopIData_chip = (USHORT *)
  1326.     AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
  1327.       return(FALSE);
  1328.  
  1329.    for (i=0; i<20; i++)
  1330.       FemaleIData_chip[i] = FemaleIData[i];
  1331.    for (i=0; i<20; i++)
  1332.       MaleIData_chip[i] = MaleIData[i];
  1333.    for (i=0; i<60; i++)
  1334.       HumanIData_chip[i] = HumanIData[i];
  1335.    for (i=0; i<60; i++)
  1336.       RobotIData_chip[i] = RobotIData[i];
  1337.    for (i=0; i<30; i++)
  1338.       FaceIData_chip[i] = FaceIData[i];
  1339.    for (i=0; i<30; i++)
  1340.       StopIData_chip[i] = StopIData[i];
  1341.  
  1342.    FemaleImage.ImageData = FemaleIData_chip;
  1343.    MaleImage.ImageData = MaleIData_chip;
  1344.    HumanImage.ImageData = HumanIData_chip;
  1345.    RobotImage.ImageData = RobotIData_chip;
  1346.    FaceImage.ImageData = FaceIData_chip;
  1347.    StopImage.ImageData = StopIData_chip;
  1348.  
  1349.    return(TRUE);
  1350. }
  1351.  
  1352. /* Deallocate the memory that was used for images,
  1353.  * See initimages for more details.
  1354.  */
  1355. freeimages()
  1356. {
  1357.    /* the images were staticly initialized above main */
  1358.    extern USHORT *FemaleIData_chip;
  1359.    extern USHORT *MaleIData_chip;
  1360.    extern USHORT *HumanIData_chip;
  1361.    extern USHORT *RobotIData_chip;
  1362.    extern USHORT *FaceIData_chip;
  1363.    extern USHORT *StopIData_chip;
  1364.  
  1365.    /* Deallocate only if the pointer is really there. */
  1366.    if (RobotIData_chip != 0)
  1367.       FreeMem(RobotIData_chip, (sizeof(RobotIData),MEMF_CHIP));
  1368.    if (HumanIData_chip != 0)
  1369.       FreeMem(HumanIData_chip, (sizeof(HumanIData),MEMF_CHIP));
  1370.    if (MaleIData_chip != 0)
  1371.       FreeMem(MaleIData_chip, (sizeof(MaleIData),MEMF_CHIP));
  1372.    if (FemaleIData_chip != 0)
  1373.       FreeMem(FemaleIData_chip, (sizeof(FemaleIData),
  1374.        MEMF_CHIP));
  1375.    if (FaceIData_chip != 0)
  1376.       FreeMem(FaceIData_chip, (sizeof(FaceIData),MEMF_CHIP));
  1377.    if (StopIData_chip != 0)
  1378.       FreeMem(StopIData_chip, (sizeof(StopIData),MEMF_CHIP));
  1379. }
  1380.